package com.smartcampusbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.smartcampusbackend.mapper.CourseMapper;
import com.smartcampusbackend.mapper.GradeMapper;
import com.smartcampusbackend.mapper.StudentCourseMapper;
import com.smartcampusbackend.mapper.UserMapper;
import com.smartcampusbackend.model.Course;
import com.smartcampusbackend.model.Grade;
import com.smartcampusbackend.model.StudentCourse;
import com.smartcampusbackend.model.User;
import com.smartcampusbackend.service.AcademicWarningService;
import com.smartcampusbackend.service.GradeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class GradeServiceImpl implements GradeService {
    
    private static final Logger logger = LoggerFactory.getLogger(GradeServiceImpl.class);
    
    // 默认平时成绩权重
    private static final Double DEFAULT_REGULAR_WEIGHT = 0.3;
    
    // 默认期末成绩权重
    private static final Double DEFAULT_EXAM_WEIGHT = 0.7;
    
    @Autowired
    private GradeMapper gradeMapper;
    
    @Autowired
    private CourseMapper courseMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private StudentCourseMapper studentCourseMapper;

    @Autowired
    private AcademicWarningService academicWarningService;

    @Override
    public List<Map<String, Object>> getStudentGrades(String studentId) {
        logger.info("获取学生成绩，studentId: {}", studentId);
        
        try {
            // 确保studentId是字符串类型
            studentId = studentId.toString();
            
            // 首先获取学生已选课程
            QueryWrapper<StudentCourse> scQuery = new QueryWrapper<>();
            scQuery.eq("student_id", studentId);
            List<StudentCourse> studentCourses = studentCourseMapper.selectList(scQuery);
            
            if (studentCourses.isEmpty()) {
                logger.info("学生没有选课记录");
                return new ArrayList<>();
            }
            
            logger.info("学生选课数量: {}", studentCourses.size());
            
            // 获取已选课程ID列表
            List<String> selectedCourseIds = studentCourses.stream()
                    .map(StudentCourse::getCourseId)
                    .collect(Collectors.toList());
            
            logger.info("学生已选课程ID: {}", selectedCourseIds);
            
            // 查询学生的所有成绩，并筛选出已选课程的成绩
            QueryWrapper<Grade> gradeQuery = new QueryWrapper<>();
            gradeQuery.eq("student_id", studentId)
                    .in("course_id", selectedCourseIds);
            List<Grade> grades = gradeMapper.selectList(gradeQuery);
            
            if (grades.isEmpty()) {
                logger.info("学生没有成绩记录");
                return new ArrayList<>();
            }
            
            logger.info("学生成绩记录数: {}", grades.size());
            
            // 获取所有相关课程ID
            List<String> courseIds = grades.stream()
                    .map(Grade::getCourseId)
                    .collect(Collectors.toList());
            
            // 查询课程信息
            List<Course> courses = courseMapper.selectBatchIds(courseIds);
            Map<String, Course> courseMap = courses.stream()
                    .collect(Collectors.toMap(Course::getId, course -> course));
            
            // 组装结果
            return grades.stream().map(grade -> {
                Map<String, Object> result = new HashMap<>();
                result.put("id", grade.getId());
                result.put("courseId", grade.getCourseId());
                result.put("regularGrade", grade.getRegularGrade());
                result.put("examGrade", grade.getExamGrade());
                result.put("finalGrade", grade.getFinalGrade());
                result.put("semester", grade.getSemester());
                
                Course course = courseMap.get(grade.getCourseId());
                if (course != null) {
                    result.put("courseName", course.getName());
                    result.put("credits", course.getCredits());
                    result.put("teacherId", course.getTeacherId());
                }
                
                return result;
            }).collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("获取学生成绩失败", e);
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    @Override
    public Map<String, Object> getStudentGradeStatistics(String studentId) {
        logger.info("获取学生成绩统计信息，studentId: {}", studentId);
        
        try {
            // 使用自定义SQL查询统计信息
            Map<String, Object> statistics = gradeMapper.getGradeStatistics(studentId);
            
            if (statistics == null) {
                statistics = new HashMap<>();
                statistics.put("totalCourses", 0);
                statistics.put("passedCourses", 0);
                statistics.put("averageGrade", 0.0);
                statistics.put("totalCredits", 0.0);
            }
            
            return statistics;
        } catch (Exception e) {
            logger.error("获取学生成绩统计信息失败", e);
            Map<String, Object> emptyStats = new HashMap<>();
            emptyStats.put("totalCourses", 0);
            emptyStats.put("passedCourses", 0);
            emptyStats.put("averageGrade", 0.0);
            emptyStats.put("totalCredits", 0.0);
            return emptyStats;
        }
    }

    @Override
    public List<Map<String, Object>> getCourseGrades(String courseId) {
        logger.info("获取课程成绩，courseId: {}", courseId);
        
        try {
            // 使用自定义SQL查询课程成绩（包含学生信息）
            return gradeMapper.getGradesByCourseWithStudentInfo(courseId);
        } catch (Exception e) {
            logger.error("获取课程成绩失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getCourseStudents(String teacherId, String courseId) {
        logger.info("获取课程学生列表，teacherId: {}, courseId: {}", teacherId, courseId);
        
        try {
            // 验证课程是否属于该教师
            Course course = courseMapper.selectById(courseId);
            if (course == null) {
                logger.warn("课程不存在，courseId: {}", courseId);
                return new ArrayList<>();
            }
            
            // 确保教师ID正确比较（处理可能的类型差异）
            String courseTeacherId = course.getTeacherId();
            if (courseTeacherId == null || (!courseTeacherId.equals(teacherId) && !courseTeacherId.toString().equals(teacherId))) {
                logger.warn("课程不属于该教师，courseId: {}, teacherId: {}, courseTeacherId: {}", 
                           courseId, teacherId, courseTeacherId);
                return new ArrayList<>();
            }
            
            logger.info("课程验证通过，课程名称: {}, 教师ID: {}", course.getName(), courseTeacherId);
            
            // 使用自定义SQL查询选课学生并包含成绩信息
            List<Map<String, Object>> result = new ArrayList<>();
            
            // 获取选课学生
            QueryWrapper<StudentCourse> scQuery = new QueryWrapper<>();
            scQuery.eq("course_id", courseId.toString());
            List<StudentCourse> studentCourses = studentCourseMapper.selectList(scQuery);
            
            if (studentCourses.isEmpty()) {
                logger.info("课程没有学生选课");
                return new ArrayList<>();
            }
            
            logger.info("找到选课记录: {} 条", studentCourses.size());
            
            // 查询已有成绩
            QueryWrapper<Grade> gradeQuery = new QueryWrapper<>();
            gradeQuery.eq("course_id", courseId.toString());
            List<Grade> grades = gradeMapper.selectList(gradeQuery);
            Map<String, Grade> gradeMap = new HashMap<>();
            for (Grade grade : grades) {
                if (grade.getStudentId() != null) {
                    gradeMap.put(grade.getStudentId().toString(), grade);
                }
            }
            
            // 逐个处理选课学生
            for (StudentCourse sc : studentCourses) {
                String studentId = sc.getStudentId() != null ? sc.getStudentId().toString() : null;
                if (studentId == null) {
                    logger.warn("选课记录的学生ID为空");
                    continue;
                }
                
                User student = null;
                try {
                    // 尝试不同方式查询学生
                    student = userMapper.selectById(studentId);
                    
                    // 如果没找到，尝试转换ID类型
                    if (student == null) {
                        try {
                            // 尝试将字符串ID解析为整数
                            Integer intId = Integer.parseInt(studentId);
                            student = userMapper.selectById(intId);
                            logger.info("通过整数ID找到学生: {}", intId);
                        } catch (NumberFormatException e) {
                            logger.warn("无法将学生ID转换为整数: {}", studentId);
                        }
                    }
                } catch (Exception e) {
                    logger.error("查询学生时出错: {}, 异常: {}", studentId, e.getMessage());
                }
                
                if (student == null) {
                    logger.warn("未找到学生信息，ID: {}", studentId);
                    continue;
                }
                
                logger.info("处理学生: id={}, name={}", student.getId(), student.getRealName());
                
                // 构建结果
                Map<String, Object> studentInfo = new HashMap<>();
                studentInfo.put("studentId", student.getId().toString());
                studentInfo.put("studentName", student.getRealName());
                studentInfo.put("studentNumber", student.getUsername());
                
                // 添加成绩信息
                Grade grade = gradeMap.get(studentId);
                if (grade != null) {
                    studentInfo.put("regularGrade", grade.getRegularGrade());
                    studentInfo.put("examGrade", grade.getExamGrade());
                    studentInfo.put("finalGrade", grade.getFinalGrade());
                } else {
                    studentInfo.put("regularGrade", null);
                    studentInfo.put("examGrade", null);
                    studentInfo.put("finalGrade", null);
                }
                
                result.add(studentInfo);
            }
            
            // 如果结果为空，尝试使用另一种方式查询
            if (result.isEmpty()) {
                logger.warn("未找到任何学生，尝试替代查询方式");
                
                // 尝试另一种查询方式：直接从用户表和选课表联合查询
                String courseIdStr = courseId.toString();
                String sql = "SELECT u.id AS studentId, u.real_name AS studentName, u.username AS studentNumber " +
                             "FROM user u JOIN student_course sc ON u.id = sc.student_id " +
                             "WHERE sc.course_id = '" + courseIdStr + "'";
                
                try {
                    List<Map<String, Object>> studentList = new ArrayList<>();
                    // 此处可以使用自定义查询实现
                    // 为简化代码，这里仅输出日志
                    logger.info("尝试直接SQL查询: {}", sql);
                    
                    // TODO: 实现自定义SQL查询
                    // 如果有自定义查询结果，将结果添加到result中
                } catch (Exception e) {
                    logger.error("替代查询失败", e);
                }
            }
            
            logger.info("返回学生列表: {} 条记录", result.size());
            return result;
        } catch (Exception e) {
            logger.error("获取课程学生列表失败", e);
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    @Override
    @Transactional
    public boolean saveOrUpdateGrade(Grade grade) {
        logger.info("保存或更新成绩，grade: {}", grade);
        
        try {
            // 确保studentId和courseId是字符串类型
            String studentId = grade.getStudentId() != null ? grade.getStudentId().toString() : null;
            String courseId = grade.getCourseId() != null ? grade.getCourseId().toString() : null;
            
            if (studentId == null || courseId == null) {
                logger.error("学生ID或课程ID为空，无法保存成绩");
                return false;
            }
            
            grade.setStudentId(studentId);
            grade.setCourseId(courseId);
            
            logger.info("处理成绩数据: studentId={}, courseId={}", studentId, courseId);
            
            // 尝试不同的查询方式验证学生是否已选课
            StudentCourse studentCourse = null;
            
            // 方法1：直接使用字符串ID查询
            QueryWrapper<StudentCourse> scQuery = new QueryWrapper<>();
            scQuery.eq("student_id", studentId)
                   .eq("course_id", courseId);
            studentCourse = studentCourseMapper.selectOne(scQuery);
            
            // 方法2：如果没找到，尝试转换为整数ID
            if (studentCourse == null) {
                try {
                    Integer intStudentId = Integer.parseInt(studentId);
                    Integer intCourseId = Integer.parseInt(courseId);
                    
                    QueryWrapper<StudentCourse> scIntQuery = new QueryWrapper<>();
                    scIntQuery.eq("student_id", intStudentId)
                           .eq("course_id", intCourseId);
                    studentCourse = studentCourseMapper.selectOne(scIntQuery);
                    logger.info("通过整数ID找到选课记录: studentId={}, courseId={}", intStudentId, intCourseId);
                } catch (NumberFormatException e) {
                    logger.warn("无法将ID转换为整数: studentId={}, courseId={}", studentId, courseId);
                }
            }
            
            // 如果真的没有选课记录，自动创建一个
            if (studentCourse == null) {
                logger.warn("未找到学生选课记录，自动创建: studentId={}, courseId={}", studentId, courseId);
                studentCourse = new StudentCourse();
                studentCourse.setStudentId(studentId);
                studentCourse.setCourseId(courseId);
                studentCourse.setSelectionDate(new Date());
                
                try {
                    studentCourseMapper.insert(studentCourse);
                    logger.info("成功创建选课记录");
                } catch (Exception e) {
                    logger.error("创建选课记录失败: {}", e.getMessage());
                    // 即使创建记录失败，也继续尝试保存成绩
                }
            }
            
            // 计算最终成绩
            if (grade.getRegularGrade() != null && grade.getExamGrade() != null) {
                Double finalGrade = calculateFinalGrade(
                        grade.getRegularGrade(),
                        grade.getExamGrade(),
                        DEFAULT_REGULAR_WEIGHT,
                        DEFAULT_EXAM_WEIGHT
                );
                grade.setFinalGrade(finalGrade);
            }
            
            // 检查是否已存在成绩记录
            QueryWrapper<Grade> query = new QueryWrapper<>();
            query.eq("student_id", studentId)
                    .eq("course_id", courseId);
            Grade existingGrade = gradeMapper.selectOne(query);
            
            // 更新或插入成绩记录
            if (existingGrade != null) {
                // 更新现有记录
                grade.setId(existingGrade.getId());
                grade.setUpdateTime(LocalDateTime.now());
                boolean result = gradeMapper.updateById(grade) > 0;
                logger.info("更新成绩记录: {}", result ? "成功" : "失败");
                // 成绩变动后自动生成学业预警
                academicWarningService.generateWarningsFromGrades();
                return result;
            } else {
                // 创建新记录
                grade.setCreateTime(LocalDateTime.now());
                grade.setUpdateTime(LocalDateTime.now());
                // 设置学期信息
                Course course = courseMapper.selectById(courseId);
                if (course != null) {
                    grade.setSemester(course.getSemester());
                }
                boolean result = gradeMapper.insert(grade) > 0;
                logger.info("创建新成绩记录: {}", result ? "成功" : "失败");
                // 成绩变动后自动生成学业预警
                academicWarningService.generateWarningsFromGrades();
                return result;
            }
        } catch (Exception e) {
            logger.error("保存或更新成绩失败", e);
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional
    public boolean batchSaveOrUpdateGrades(List<Grade> grades) {
        logger.info("批量保存或更新成绩，数量: {}", grades != null ? grades.size() : 0);
        if (grades == null || grades.isEmpty()) {
            logger.warn("成绩列表为空");
            return false;
        }
        
        boolean allSuccess = true;
        int successCount = 0;
        int failCount = 0;
        
        // 记录处理成绩的课程ID，用于后续验证
        Set<String> processedCourses = new HashSet<>();
        
        for (Grade grade : grades) {
            try {
                if (saveOrUpdateGrade(grade)) {
                    successCount++;
                    if (grade.getCourseId() != null) {
                        processedCourses.add(grade.getCourseId().toString());
                    }
                } else {
                    failCount++;
                    allSuccess = false;
                    logger.warn("成绩保存失败: studentId={}, courseId={}", 
                              grade.getStudentId(), grade.getCourseId());
                }
            } catch (Exception e) {
                failCount++;
                allSuccess = false;
                logger.error("成绩保存异常: {}", e.getMessage());
            }
        }
        
        logger.info("批量保存或更新成绩完成，成功: {}，失败: {}", successCount, failCount);
        
        // 批量成绩变动后自动生成学业预警
        academicWarningService.generateWarningsFromGrades();
        
        // 在处理完成后检查所有已处理课程的学生列表与成绩记录是否匹配
        for (String courseId : processedCourses) {
            try {
                checkAndRepairCourseGradeRecords(courseId);
            } catch (Exception e) {
                logger.error("检查课程成绩记录失败: courseId={}, error={}", courseId, e.getMessage());
            }
        }
        
        return allSuccess;
    }
    
    /**
     * 检查并修复课程成绩记录
     * 确保所有选课的学生都有对应的成绩记录
     */
    private void checkAndRepairCourseGradeRecords(String courseId) {
        logger.info("检查课程成绩记录完整性: courseId={}", courseId);
        
        if (courseId == null) {
            return;
        }
        
        try {
            // 获取所有选课学生
            QueryWrapper<StudentCourse> scQuery = new QueryWrapper<>();
            scQuery.eq("course_id", courseId.toString());
            List<StudentCourse> studentCourses = studentCourseMapper.selectList(scQuery);
            
            if (studentCourses.isEmpty()) {
                logger.info("没有学生选修此课程: courseId={}", courseId);
                return;
            }
            
            // 获取现有成绩记录
            QueryWrapper<Grade> gradeQuery = new QueryWrapper<>();
            gradeQuery.eq("course_id", courseId.toString());
            List<Grade> existingGrades = gradeMapper.selectList(gradeQuery);
            
            // 构建学生ID到成绩的映射
            Map<String, Grade> gradeMap = new HashMap<>();
            for (Grade grade : existingGrades) {
                if (grade.getStudentId() != null) {
                    gradeMap.put(grade.getStudentId().toString(), grade);
                }
            }
            
            // 获取课程信息
            Course course = courseMapper.selectById(courseId);
            String semester = course != null ? course.getSemester() : "2023-2024-1";
            
            // 检查每个选课学生是否有成绩记录
            int addedCount = 0;
            for (StudentCourse sc : studentCourses) {
                if (sc.getStudentId() == null) {
                    continue;
                }
                
                String studentId = sc.getStudentId().toString();
                // 如果没有成绩记录，创建一个空记录
                if (!gradeMap.containsKey(studentId)) {
                    Grade newGrade = new Grade();
                    newGrade.setStudentId(studentId);
                    newGrade.setCourseId(courseId);
                    newGrade.setSemester(semester);
                    newGrade.setCreateTime(LocalDateTime.now());
                    newGrade.setUpdateTime(LocalDateTime.now());
                    
                    try {
                        gradeMapper.insert(newGrade);
                        addedCount++;
                    } catch (Exception e) {
                        logger.error("创建空成绩记录失败: studentId={}, courseId={}, error={}", 
                                   studentId, courseId, e.getMessage());
                    }
                }
            }
            
            if (addedCount > 0) {
                logger.info("为课程添加了 {} 条缺失的成绩记录: courseId={}", addedCount, courseId);
            }
        } catch (Exception e) {
            logger.error("检查课程成绩记录时出错: courseId={}, error={}", courseId, e.getMessage());
        }
    }

    @Override
    public Double calculateFinalGrade(Double regularGrade, Double examGrade, Double regularWeight, Double examWeight) {
        // 如果权重未指定，使用默认值
        if (regularWeight == null) {
            regularWeight = DEFAULT_REGULAR_WEIGHT;
        }
        if (examWeight == null) {
            examWeight = DEFAULT_EXAM_WEIGHT;
        }
        
        // 计算最终成绩
        Double finalGrade = regularGrade * regularWeight + examGrade * examWeight;
        
        // 四舍五入到一位小数
        return Math.round(finalGrade * 10) / 10.0;
    }
} 